@page "/chat"
@inherits LiveComponentBase<ChatState.Local, ChatState>
@inject NavigationManager Navigator
@inject IChatService ChatService

@{
    var local = Local;
    var state = State;
    var lastPage = state.LastPage;
    var lastUpdateError = LiveState.LastUpdateError;
}

<div>
    <span class="float-right">
        <span class="badge btn-primary">
            @(state.ActiveUserCount) <span class="oi oi-chat"></span>
        </span>
        <span class="badge btn-light">
            @(state.UserCount) <span class="oi oi-people"></span>
        </span>
    </span>
    <h1>Chat</h1>
</div>

<p>
    To see the state replication in action,
    <a href="@Navigator.Uri" target="_blank">open this chat</a> or
    <a href="/composition" target="_blank">Composition example</a>
    in another window.
</p>

@if (local.Error != null) {
    <div class="alert alert-danger" role="alert">
        @local.Error.Message
    </div>
}
@if (lastUpdateError != null) {
    <div class="alert alert-warning" role="alert">
        Update error: @lastUpdateError.Message
    </div>
}

<form @onsubmit="@SetNameAsync">
    <div class="input-group pb-3">
        <div class="input-group-prepend">
            <span class="input-group-text">Your name</span>
        </div>
        <input class="form-control" @bind-value="@local.MyName"/>
        <div class="input-group-append">
            <button type="submit" class="btn btn-warning">Change</button>
        </div>
    </div>
</form>

<table class="table table-sm table-striped">
    <thead>
    <tr>
        <th scope="col">User</th>
        <th scope="col">Message</th>
    </tr>
    </thead>
    <tbody>
    @foreach(var message in lastPage.Messages) {
        var user = lastPage.Users[message.UserId];
        {
            <tr>
                <td style="width: 20%; max-width: 33%">@user.Name</td>
                <td style="width: auto; min-width: 67%">@message.Text</td>
            </tr>
        }
    }
    </tbody>
</table>

<form @onsubmit="@SendMessageAsync">
    <div class="input-group pb-3">
        <div class="input-group-prepend">
            <span class="input-group-text">Message</span>
        </div>
        <input class="form-control"
            placeholder="No ideas? Send an empty one!"
            @bind-value="@local.MyMessage" />
        <div class="input-group-append">
            <button type="submit" class="btn btn-success">Send</button>
        </div>
    </div>
</form>

@code {
    protected override async Task OnInitializedAsync()
    {
        if (Local.Me == null)
            // Let's pre-create the user
            await SetNameAsync();
        else
            UpdateLocal(s => s.MyName = s.Me?.Name ?? "");
    }

    private async Task SetNameAsync()
    {
        ResetError();
        var local = Local;
        try {
            if (local.Me != null) {
                try {
                    var user1 = await ChatService.SetUserNameAsync(local.Me.Id, local.MyName);
                    UpdateLocal(s => s.Me = user1);
                    return;
                }
                catch {
                    // Prob. the user doesn't exist (server restarted), so we should try to recreate it.
                }
            }
            var user2 = await ChatService.CreateUserAsync(local.MyName);
            UpdateLocal(s => s.Me = user2);
        }
        catch (Exception e) {
            SetError(e);
        }
   }

    private async Task SendMessageAsync()
    {
        ResetError();
        try {
            var local = Local;
            if (local.Me == null)
                throw new ApplicationException("Please set your name first.");
            await ChatService.AddMessageAsync(local.Me.Id, local.MyMessage);
            UpdateLocal(s => s.MyMessage = "");
        }
        catch (Exception e) {
            SetError(e);
        }
    }

    private void ResetError() => SetError(null);

    private void SetError(Exception? error)
        => UpdateLocal(local => local.Error = error);
}
